#include "mainwidget.h"
#include "ui_mainwidget.h"
#include  <time.h>
#include <QMessageBox>
#include <QPainter>
#include <QKeyEvent>
#include <QtDebug>

//定义方块图案代码和边界
//田字形状
int item1[4][4]={
    {0,0,0,0},
    {0,1,1,0},
    {0,1,1,0},
    {0,0,0,0}
};

//左L
int item2[4][4]={
    {0,1,0,0},
    {0,1,0,0},
    {0,1,1,0},
    {0,0,0,0}
};

//右L
int item3[4][4]={
    {0,0,1,0},
    {0,0,1,0},
    {0,1,1,0},
    {0,0,0,0}
};

//长条形状
int item4[4][4]={
    {0,0,0,0},
    {1,1,1,1},
    {0,0,0,0},
    {0,0,0,0}
};

//左S
int item5[4][4]={
    {0,0,1,0},
    {0,1,1,0},
    {0,1,0,0},
    {0,0,0,0}
};

//山形
int item6[4][4]={
    {0,0,0,0},
    {0,0,1,0},
    {0,1,1,1},
    {0,0,0,0}
};

//竖条
int item7[4][4]={
    {0,0,1,0},
    {0,0,1,0},
    {0,0,1,0},
    {0,0,1,0}
};


//拷贝方块图案
inline void block_copy(int dblock[4][4],int sblock[4][4]){
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            dblock[i][j]=sblock[i][j];
        }
    }
}

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWidget)
{
    ui->setupUi(this);

    //设置窗口标题名称
    setWindowTitle("俄罗斯方块游戏");

    //禁止用户使用最大化按钮
    setWindowFlags(windowFlags()& ~Qt::WindowMaximizeButtonHint);

    //固定窗口大小（移除了分数显示区域的宽度）
    setFixedSize(AREA_COL*BLOCK_SIZE+MARGIN*3+4*BLOCK_SIZE,AREA_ROW*BLOCK_SIZE+MARGIN*2);

    //设置游戏背景
    QPixmap bkground("d://1.jpg");
    bkground=bkground.scaled(this->size(),Qt::IgnoreAspectRatio);
    QPalette palatte;
    palatte.setBrush(QPalette::Window,bkground);
    this->setPalette(palatte);

    //初始化游戏
    InitGameFunc();
}

MainWidget::~MainWidget()
{
    delete ui;
}

void MainWidget::InitGameFunc()
{
    for(int i=0;i<AREA_ROW;i++){
        for(int j=0;j<AREA_COL;j++){
            game_area[i][j]=0;
        }
    }
    speed_ms=800;
    refresh_ms=30;

    srand(time(0));

    game_over = false;

    //游戏开始
    StartGameFunc();
}

void MainWidget::StartGameFunc()
{
    game_timer=startTimer(speed_ms);
    paint_timer=startTimer(refresh_ms);

    //产生初始化下一个方块
    int block_id=rand()%7;

    CreateBlock(next_block,block_id);

    //产生方块
    ResetBlock();
}

void MainWidget::GameOverFunc()
{
    killTimer(game_timer);
    killTimer(paint_timer);

    game_over = true;

    QMessageBox::information(this, "游戏结束", "游戏结束!");

    //可以选择重新开始游戏
    InitGameFunc();
}

void MainWidget::ResetBlock()
{
    //将下一个方块设置为当前方块
    block_copy(current_block, next_block);

    //随机生成下一个方块
    int block_id = rand() % 7;
    CreateBlock(next_block, block_id);

    //设置当前方块的初始位置
    block_pos.pos_x = AREA_COL / 2 - 2;
    block_pos.pos_y = 0;

    //检查游戏是否结束（新方块与已有方块重叠）
    if (IsCollide(block_pos.pos_x, block_pos.pos_y, DOWN)) {
        GameOverFunc();
    }
}

void MainWidget::BlockMove(Direction dir)
{
    int new_x = block_pos.pos_x;
    int new_y = block_pos.pos_y;

    //根据方向更新位置
    if (dir == LEFT) {
        new_x--;
    } else if (dir == RIGHT) {
        new_x++;
    } else if (dir == DOWN) {
        new_y++;
    }

    //检查是否可以移动
    if (!IsCollide(new_x, new_y, dir)) {
        block_pos.pos_x = new_x;
        block_pos.pos_y = new_y;

        //如果是下移，检查是否需要固定
        if (dir == DOWN) {
            //检查是否到达底部或碰到其他方块
            if (IsCollide(block_pos.pos_x, block_pos.pos_y + 1, DOWN)) {
                //将方块固定到游戏区域
                ConvertStable(block_pos.pos_x, block_pos.pos_y);

                //检查并消除已满的行
                CheckLines();

                //生成新的方块
                ResetBlock();
            }
        }
    }
}

void MainWidget::BlockRotate(int block[4][4])
{
    int temp[4][4];

    //创建旋转后的临时方块
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            temp[j][3 - i] = block[i][j];
        }
    }

    //检查旋转后是否会碰撞
    if (!IsCollide(block_pos.pos_x, block_pos.pos_y, DOWN, temp)) {
        //如果不会碰撞，则应用旋转
        block_copy(block, temp);
    }
}

//重载IsCollide函数，用于旋转检测
bool MainWidget::IsCollide(int x, int y, Direction dir, int block[4][4])
{
    //计算边界
    Border border;
    GetBorder(block, border);

    //检查边界是否超出游戏区域
    if (dir == LEFT && (x + border.lbound < 0)) {
        return true;
    }

    if (dir == RIGHT && (x + border.rbound >= AREA_COL)) {
        return true;
    }

    if (dir == DOWN && (y + border.dbound >= AREA_ROW)) {
        return true;
    }

    //检查是否与已有的稳定方块碰撞
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (block[i][j] == 1) {
                int pos_x = x + j;
                int pos_y = y + i;

                if (pos_y >= 0 && pos_y < AREA_ROW && pos_x >= 0 && pos_x < AREA_COL) {
                    if (game_area[pos_y][pos_x] == 1) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

bool MainWidget::IsCollide(int x, int y, Direction dir)
{
    return IsCollide(x, y, dir, current_block);
}

void MainWidget::CreateBlock(int block[4][4], int block_id)
{
    switch(block_id){
    case 0:
        block_copy(block, item1);
        break;
    case 1:
        block_copy(block, item2);
        break;
    case 2:
        block_copy(block, item3);
        break;
    case 3:
        block_copy(block, item4);
        break;
    case 4:
        block_copy(block, item5);
        break;
    case 5:
        block_copy(block, item6);
        break;
    case 6:
        block_copy(block, item7);
        break;
    default:
        break;
    }
}

void MainWidget::GetBorder(int block[4][4], Border &border)
{
    border.lbound = 4;
    border.rbound = -1;
    border.dbound = -1;

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (block[i][j] == 1) {
                if (j < border.lbound) {
                    border.lbound= j;
                }
                if (j > border.rbound) {
                    border.rbound = j;
                }
                if (i > border.dbound) {
                    border.dbound = i;
                }
            }
        }
    }
}

void MainWidget::ConvertStable(int x, int y)
{
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (current_block[i][j] == 1) {
                int pos_x = x + j;
                int pos_y = y + i;

                if (pos_y >= 0 && pos_y < AREA_ROW && pos_x >= 0 && pos_x < AREA_COL) {
                    game_area[pos_y][pos_x] = 1;
                }
            }
        }
    }
}

void MainWidget::CheckLines()
{
    bool line_removed = false;

    // 检查每一行
    for (int i = AREA_ROW - 1; i >= 0; i--) {
        bool is_line_full = true;

        // 检查当前行是否已满
        for (int j = 0; j < AREA_COL; j++) {
            if (game_area[i][j] == 0) {
                is_line_full = false;
                break;
            }
        }

        // 如果当前行已满，则消除该行
        if (is_line_full) {
            line_removed = true;

            // 将上面的所有行下移一行
            for (int k = i; k > 0; k--) {
                for (int j = 0; j < AREA_COL; j++) {
                    game_area[k][j] = game_area[k-1][j];
                }
            }

            // 顶部行清空
            for (int j = 0; j < AREA_COL; j++) {
                game_area[0][j] = 0;
            }

            // 由于行已经下移，需要重新检查当前行
            i++;
        }

        // 如果已经移除了一行，需要重新检查当前行（因为上面的行已经下移）
        if (line_removed) {
            line_removed = false;
            i++; // 重新检查当前行
        }
    }
}

void MainWidget::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == game_timer) {
        // 自动下落
        BlockMove(DOWN);
    } else if (event->timerId() == paint_timer) {
        // 刷新界面
        update();
    }
}

void MainWidget::keyPressEvent(QKeyEvent *event)
{
    if (game_over) {
        return;
    }

    switch (event->key()) {
    case Qt::Key_Left:
        BlockMove(LEFT);
        break;
    case Qt::Key_Right:
        BlockMove(RIGHT);
        break;
    case Qt::Key_Down:
        BlockMove(DOWN);
        break;
    case Qt::Key_Up:
        BlockRotate(current_block);
        break;
    case Qt::Key_Space:
        //快速下落到底部
        while (!IsCollide(block_pos.pos_x, block_pos.pos_y + 1, DOWN)) {
            block_pos.pos_y++;
        }
        ConvertStable(block_pos.pos_x, block_pos.pos_y);
        CheckLines();
        ResetBlock();
        break;
    default:
        QWidget::keyPressEvent(event);
    }
}

void MainWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    //绘制游戏区域边框
    QRect gameAreaRect(MARGIN, MARGIN, AREA_COL * BLOCK_SIZE, AREA_ROW * BLOCK_SIZE);
    painter.setPen(QPen(Qt::black, 2));
    painter.drawRect(gameAreaRect);

    //绘制游戏区域网格
    painter.setPen(QPen(Qt::gray, 1));
    for (int i = 0; i <= AREA_ROW; i++) {
        painter.drawLine(MARGIN, MARGIN + i * BLOCK_SIZE,
                         MARGIN + AREA_COL * BLOCK_SIZE, MARGIN + i * BLOCK_SIZE);
    }
    for (int j = 0; j <= AREA_COL; j++) {
        painter.drawLine(MARGIN + j * BLOCK_SIZE, MARGIN,
                         MARGIN + j * BLOCK_SIZE, MARGIN + AREA_ROW * BLOCK_SIZE);
    }

    //绘制稳定方块
    painter.setBrush(QBrush(Qt::white));
    for (int i = 0; i < AREA_ROW; i++) {
        for (int j = 0; j < AREA_COL; j++) {
            if (game_area[i][j] == 1) {
                QRect blockRect(MARGIN + j * BLOCK_SIZE, MARGIN + i * BLOCK_SIZE,
                                BLOCK_SIZE - 1, BLOCK_SIZE - 1);
                painter.drawRect(blockRect);
                painter.fillRect(blockRect, Qt::white);
            }
        }
    }

    //绘制当前活动方块
    painter.setBrush(QBrush(Qt::red));
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (current_block[i][j] == 1) {
                int pos_x = block_pos.pos_x + j;
                int pos_y = block_pos.pos_y + i;

                if (pos_y >= 0) {
                    QRect blockRect(MARGIN + pos_x * BLOCK_SIZE, MARGIN + pos_y * BLOCK_SIZE,
                                    BLOCK_SIZE - 1, BLOCK_SIZE - 1);
                    painter.drawRect(blockRect);
                    painter.fillRect(blockRect, Qt::red);
                }
            }
        }
    }

    //绘制下一个方块预览区域（位置调整，移除分数显示占用的空间）
    QRect nextAreaRect(MARGIN * 2 + AREA_COL * BLOCK_SIZE, MARGIN,
                       4 * BLOCK_SIZE, 4 * BLOCK_SIZE);
    painter.setPen(QPen(Qt::black, 2));
    painter.drawRect(nextAreaRect);

    //绘制预览区域网格
    painter.setPen(QPen(Qt::gray, 1));
    for (int i = 0; i <= 4; i++) {
        painter.drawLine(MARGIN * 2 + AREA_COL * BLOCK_SIZE, MARGIN + i * BLOCK_SIZE,
                         MARGIN * 2 + AREA_COL * BLOCK_SIZE + 4 * BLOCK_SIZE, MARGIN + i * BLOCK_SIZE);
    }
    for (int j = 0; j <= 4; j++) {
        painter.drawLine(MARGIN * 2 + AREA_COL * BLOCK_SIZE + j * BLOCK_SIZE, MARGIN,
                         MARGIN * 2 + AREA_COL * BLOCK_SIZE + j * BLOCK_SIZE, MARGIN + 4 * BLOCK_SIZE);
    }

    //绘制下一个方块
    painter.setBrush(QBrush(Qt::white));
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (next_block[i][j] == 1) {
                QRect blockRect(MARGIN * 2 + AREA_COL * BLOCK_SIZE + j * BLOCK_SIZE,
                                MARGIN + i * BLOCK_SIZE, BLOCK_SIZE - 1, BLOCK_SIZE - 1);
                painter.drawRect(blockRect);
                painter.fillRect(blockRect, Qt::white);
            }
        }
    }
}
